package handler

import (
	"errors"
	"fmt"
	"net/http"
	"ruoyi-go-echo-ddd/internal/application"
	"ruoyi-go-echo-ddd/internal/domain/model"
	"ruoyi-go-echo-ddd/internal/infrastructure/http/request"
	"ruoyi-go-echo-ddd/internal/infrastructure/http/response"
	"ruoyi-go-echo-ddd/internal/infrastructure/utils"

	"github.com/labstack/echo/v4"
	"github.com/rs/zerolog"
	"github.com/spf13/cast"
)

type SysRoleHandler struct {
	roleApp  *application.SysRoleApplication
	userApp  *application.SysUserApplication
	tokenApp *application.TokenApplication
	permApp  *application.PermissionApplication
}

func NewSysRoleHandler(
	r *application.SysRoleApplication,
	u *application.SysUserApplication,
	t *application.TokenApplication,
	p *application.PermissionApplication) *SysRoleHandler {
	return &SysRoleHandler{
		roleApp:  r,
		userApp:  u,
		tokenApp: t,
		permApp:  p,
	}
}

// SaveHandler 角色新增
// @Summary 角色新增
// @Description 角色新增
// @Tags 角色管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param param body model.SysRoleInsert true "角色新增参数"
// @Success 200 {object} response.Result{data=model.SysRole} "新增成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/role [post]
func (controller *SysRoleHandler) SaveHandler(c echo.Context) error {
	var param *model.SysRoleInsert
	if err := c.Bind(&param); err != nil {
		response.NewRespCodeMsg(c, 500, "系统角色新增参数解析错误")
		return err
	}

	sysRole := model.SysRoleInsertConvertToEntity(param)

	roleNameExist, err := controller.roleApp.VerifyRoleNameExist(c, sysRole)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	if roleNameExist {
		response.NewRespCodeMsg(c, 500, "名称已存在")
		return err
	}

	roleKeyExist, err := controller.roleApp.VerifyRoleKeyExist(c, sysRole)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	if roleKeyExist {
		response.NewRespCodeMsg(c, 500, "权限字符已存在")
		return err
	}

	user, err := controller.tokenApp.GetLoginUser(c)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	if user != nil {
		sysRole.CreateBy = user.Username
	}
	sysRole.CreateTime = model.LocalDateTimeNow("")

	result, err := controller.roleApp.Insert(c, sysRole)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	response.NewResponse(c, 200, "系统角色信息新增成功", result)
	return nil
}

// UpdateHandler 角色更新
// @Summary 角色更新
// @Description 角色更新
// @Tags 角色管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param dept body model.SysRole true "角色信息"
// @Success 200 {object} response.Result{data=int64} "更新成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/role [put]
func (controller *SysRoleHandler) UpdateHandler(c echo.Context) error {
	var sysRole *model.SysRole
	if err := c.Bind(&sysRole); err != nil {
		response.NewRespCodeMsg(c, 500, "系统角色更新参数解析错误")
		return err
	}

	if sysRole.Id == 0 {
		response.NewRespCodeMsg(c, 500, "系统角色ID不能为空")
		return errors.New("系统角色ID不能为空")
	}

	roleIsAllowed := controller.roleApp.VerifyRoleIsAllowed(sysRole)
	if roleIsAllowed {
		response.NewRespCodeMsg(c, 500, "管理员不允许操作")
		return errors.New("管理员不允许操作")
	}

	roleNameExist, err := controller.roleApp.VerifyRoleNameExist(c, sysRole)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	if roleNameExist {
		response.NewRespCodeMsg(c, 500, "名称已存在")
		return errors.New("名称已存在")
	}

	roleKeyExist, err := controller.roleApp.VerifyRoleKeyExist(c, sysRole)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	if roleKeyExist {
		response.NewRespCodeMsg(c, 500, "权限字符已存在")
		return errors.New("权限字符已存在")
	}

	result, err := controller.roleApp.Update(c, sysRole)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	// 更新用户缓存
	loginUser, err := controller.tokenApp.GetLoginUser(c)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	if loginUser != nil && model.IsAdmin(loginUser.UserId) {
		permissions, menuPermissionErr := controller.permApp.SelectMenuPermission(c, loginUser.UserId)
		if menuPermissionErr != nil {
			response.NewRespCodeErr(c, 500, menuPermissionErr)
			return errors.New("获取用户菜单失败")
		}
		loginUser.Permissions = permissions
		user, userErr := controller.userApp.SelectByUsername(c, loginUser.Username)
		if userErr != nil {
			response.NewRespCodeErr(c, 500, err)
			return errors.New("获取用户信息失败")
		}
		user.IsAdmin = model.IsAdmin(user.Id)
		loginUser.User = user
		if serUserErr := controller.tokenApp.SetLoginUser(c, loginUser); serUserErr != nil {
			response.NewRespCodeErr(c, 500, serUserErr)
			return errors.New("设置用户信息失败")
		}
	}

	response.NewResponse(c, 200, "系统角色信息更新成功", result)
	return nil
}

// BatchSaveHandler 批量新增
// @Summary 角色批量新增
// @Description 角色批量新增
// @Tags 角色管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param dept body []model.SysRole true "角色集合"
// @Success 200 {object} response.Result{data=[]int64} "批量新增成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/role/batchSave [post]
func (controller *SysRoleHandler) BatchSaveHandler(c echo.Context) error {
	var list []*model.SysRole
	if err := c.Bind(&list); err != nil {
		response.NewRespCodeMsg(c, 500, "系统角色批量新增参数解析错误")
		return err
	}

	result, err := controller.roleApp.BatchInsert(c, list)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	response.NewResponse(c, 200, "系统角色批量新增成功", result)
	return nil
}

// SelectPageHandler 分页查询处理器
// @Summary 分页查询
// @Description 角色分页查询
// @Tags 角色管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param req query request.RolePageParam false "分页查询参数"
// @Success 200 {object} response.Result{data=[]int64} "批量新增成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/role/list [get]
func (controller *SysRoleHandler) SelectPageHandler(c echo.Context) error {
	req := new(request.RolePageParam)
	if err := c.Bind(req); err != nil {
		response.NewRespCodeMsg(c, http.StatusInternalServerError, "分页参数解析失败")
		return err
	}

	list, total, page, err := controller.roleApp.SelectPage(c, req)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	pageData := response.NewPageData(list, total, page)

	response.NewResponse(c, 200, "系统公告分页查询成功", pageData)
	return nil
}

// SelectOneHandler 角色查询
// @Summary 角色查询
// @Description 通过ID查询角色
// @Tags 角色管理
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param id path string true "角色主键ID"
// @Success 200 {object} response.Result{data=model.SysRole} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/role/{id} [get]
func (controller *SysRoleHandler) SelectOneHandler(c echo.Context) error {
	id := c.Param("id")

	data, err := controller.roleApp.SelectById(c, cast.ToInt64(id))
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	response.NewResponse(c, 200, "查询成功", data)
	return nil
}

// BatchDeleteHandler 批量删除
// @Summary 角色批量删除
// @Description 通过ID批量删除角色
// @Tags 角色管理
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param ids path string true "英文逗号分割的角色主键ID"
// @Success 200 {object} response.Result{data=int64} "删除成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/role/{ids} [delete]
func (controller *SysRoleHandler) BatchDeleteHandler(c echo.Context) error {
	ids, err := GlobalDeleteHandler(c, "id")
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}

	count, err := controller.roleApp.BatchDelete(c, ids)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	response.NewResponse(c, 200, "批量删除成功", count)
	return nil
}

// SelectListHandler 查询角色分片处理器
// @Summary 角色列表查询
// @Description 查询所有角色信息
// @Tags 角色管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param ids body []int64 false "角色ID集合"
// @Success 200 {object} response.Result{data=[]model.SysRole} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/role/list [post]
func (controller *SysRoleHandler) SelectListHandler(c echo.Context) error {
	var ids []int64
	if err := c.Bind(&ids); err != nil {
		response.NewRespCodeMsg(c, 500, "系统角色查询参数解析错误")
		return err
	}

	list, err := controller.roleApp.SelectList(c, ids)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	response.NewResponse(c, 200, "查询成功", list)
	return nil
}

// SelectIdListHandler 角色ID切片处理器
// @Summary 查询用户角色ID集合
// @Description 查询用户角色ID集合
// @Tags 角色管理
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param userId query string true "角色ID"
// @Success 200 {object} response.Result{data=[]int64} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/role/list/user [get]
func (controller *SysRoleHandler) SelectIdListHandler(c echo.Context) error {
	list, err := controller.roleApp.SelectIdsByUserId(c, c.QueryParam("userId"))
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	response.NewResponse(c, 200, "查询成功", list)
	return nil
}

// SelectAllHandler 查询所有
// @Summary 查询所有角色
// @Description 查询所有角色集合
// @Tags 角色管理
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Success 200 {object} response.Result{data=[]model.SysRole} "查询成功"
// @Failure 500 {object} response.Result "系统错误"
// @Router /system/role/selectAll [get]
func (controller *SysRoleHandler) SelectAllHandler(c echo.Context) error {
	allRole, err := controller.roleApp.SelectAll(c)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	response.NewResponse(c, 200, "查询成功", allRole)
	return nil
}

// DataScopeHandler 分配数据权限
// @Summary 分配数据权限
// @Description 分配数据权限
// @Tags 角色管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Param dataScope body model.SysRoleDataScope true "数据权限参数"
// @Security ApiKeyAuth
// @Success 200 {object} response.Result "操作成功"
// @Failure 500 {object} response.Result "系统错误"
// @Router /system/role/dataScope [put]
func (controller *SysRoleHandler) DataScopeHandler(c echo.Context) error {
	var dataScope *model.SysRoleDataScope
	if err := c.Bind(&dataScope); err != nil {
		zerolog.DefaultContextLogger.Error().Err(err).Msg("分配数据权限参数错误")
		response.NewRespCodeMsg(c, 500, "分配数据权限参数错误")
		return err
	}

	roleDataScope := model.SysRoleDataScopeConvertToEntity(dataScope)

	allowed := VerifyRoleAllowed(roleDataScope)
	if !allowed {
		response.NewRespCodeMsg(c, 500, "不允许修改管理员数据权限")
		return errors.New("不允许修改管理员数据权限")
	}

	result, err := controller.roleApp.UpdateWithOutMenuAndDataScope(c, roleDataScope)
	if err != nil {
		zerolog.DefaultContextLogger.Error().Err(err).Msg("分配数据权限操作错误")
		response.NewRespCodeMsg(c, 500, "分配数据权限操作错误")
		return err
	}
	response.NewRespCodeMsg(c, 200, fmt.Sprintf("操作成功，更新了：%d条数据", result))
	return nil
}

// ExportExcelBufferHandler 导出Excel，使用缓冲流
// @Summary 导出Excel
// @Description 导出Excel-使用缓冲流
// @Tags 角色管理
// @Produce application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Success 200 {file} file "Excel文件"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/role/export [get]
func (controller *SysRoleHandler) ExportExcelBufferHandler(c echo.Context) error {
	data, err := controller.roleApp.SelectAllForExcel(c)
	if err != nil {
		response.NewRespCodeErr(c, 500, err)
		return err
	}
	headers := []string{"主键ID", "角色名称", "权限字符", "排序", "数据范围", "菜单树选择项是否关联显示", "部门树选择项是否关联显示", "角色状态(0正常 1停用)", "删除标志(0代表存在 2代表删除)", "创建人", "创建时间", "修改人", "修改时间", "备注信息"}
	return DownloadExcelBuffer(c, "角色信息_"+utils.TimeNowFormat("")+".xlsx", "角色信息", headers, data, true)
}
